package com.efast.cafe.portal.controller.doc;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.efast.cafe.commponent.log.ext.CafeLogger;
import com.efast.cafe.commponent.log.ext.CafeLoggerFactory;
import com.efast.cafe.framework.bean.FileChunkInfo;
import com.efast.cafe.framework.bean.ResultBean;
import com.efast.cafe.framework.controller.AbstractController;
import com.efast.cafe.framework.exception.ServiceException;
import com.efast.cafe.framework.util.DocConstant;
import com.efast.cafe.framework.util.SpringWebUtils;
import com.efast.cafe.portal.bean.doc.DocFileFormBean;
import com.efast.cafe.portal.bean.doc.DocFileHisQueryBean;
import com.efast.cafe.portal.bean.doc.DocFileListParamBean;
import com.efast.cafe.portal.bean.doc.DocFilesBean;
import com.efast.cafe.portal.bean.doc.DocPortalQuery;
import com.efast.cafe.portal.entity.doc.DocFileHis;
import com.efast.cafe.portal.entity.doc.DocFiles;
import com.efast.cafe.portal.service.doc.IDocFilesService;
import com.efast.cafe.portal.service.doc.IDocFolderService;
import com.efast.cafe.portal.service.doc.IDocUserService;
import com.efast.cafe.util.AliyunOSSUtil;
import com.efast.cafe.util.ConfigUtil;
import com.efast.cafe.util.FileUploadUtil;
import com.efast.cafe.util.FileUtil;
import com.efast.cafe.util.StringUtil;
import com.efast.cafe.util.date.DateUtils;

@Controller
@RequestMapping("/doc")
public class DocFilesController extends AbstractController {
	
	CafeLogger logger = CafeLoggerFactory.getLogger(getClass());

	@Autowired
	private IDocFilesService docFilesService;
	@Autowired
	private IDocFolderService docFolderService;
	@Autowired
	private IDocUserService docUserService;
	

	// 企业文件列表
	@RequestMapping(value = "/files/list", method = RequestMethod.POST)
	public @ResponseBody ResultBean queryCompanyFilesByFolder(@RequestBody DocFileListParamBean docFileListParamBean) {
		ResultBean result = new ResultBean(true, null);
		try {
			result.setObject(docFilesService.queryCompanyFilesByFolder(docFileListParamBean));
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}
		}
		return result;
	}

	// 我的文件列表
	@RequestMapping(value = "/myFiles/list", method = RequestMethod.POST)
	public @ResponseBody ResultBean queryMyFilesByFolder(@RequestBody DocFileListParamBean docFileListParamBean) {
		ResultBean result = new ResultBean(true, null);
		try {
			result.setObject(docFilesService.queryMyFilesByFolder(docFileListParamBean));
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}
		}
		return result;
	}

	// 查看文件详细
	@RequestMapping(value = "/files/detail", method = RequestMethod.POST)
	public @ResponseBody ResultBean queryFilesDetail(@RequestBody DocPortalQuery query) {
		ResultBean result = new ResultBean(true, null);
		try {
			result.setObject(docFilesService.queryFilesDetail(query.getType(), query.getId()));

		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}
		}
		return result;
	}

	// 文件重命名
	@RequestMapping(value = "/files/updateName", method = RequestMethod.POST)
	public @ResponseBody ResultBean updateFilesName(@RequestBody DocPortalQuery query) {
		ResultBean result = new ResultBean(true, null);
		try {
			docFilesService.updateFilesName(query.getType(), query.getId(), query.getRealName());
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}
		}
		return result;
	}

	// 文件取消签出
	@RequestMapping(value = "/files/cancleCheckOut", method = RequestMethod.POST)
	public @ResponseBody ResultBean filesCancleCheckOut(@RequestBody Map<String, Integer> map) {
		ResultBean result = new ResultBean(true, null);
		Integer id = null;
		if (map.containsKey("id")) {
			id = map.get("id");
		}
		try {
			docFilesService.filesCancleCheckOut(id);

		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}
		}
		return result;
	}

	// 文件签出
	@RequestMapping(value = "/files/checkOut", method = RequestMethod.POST)
	public @ResponseBody ResultBean filesCheckOut(@RequestParam Integer id, @RequestParam(required = false) String type,
			HttpServletResponse response) {
		ResultBean result = new ResultBean(true, null);
		try {
			DocFiles doc = docFilesService.queryFilesDetail(type, id);
			docFilesService.filesCheckOut(id);
			download(doc.getFilePath() + doc.getSysName(), response, doc.getRealName());

		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}

		}
		return result;
	}

	// 文件签入
	@RequestMapping(value = "/files/checkIn", method = RequestMethod.POST)
	public @ResponseBody ResultBean filesCheckIn(@RequestParam("files") MultipartFile file, FileChunkInfo chunkInfo,
			HttpServletResponse response, HttpServletRequest request, @RequestParam("id") Integer id) {
		ResultBean result = new ResultBean(true, null);
		try {
			if (id == null) {
				throw new ServiceException("签入失败");
			}
			if (!SpringWebUtils.getRequestUser()
					.equals(docFilesService.queryFilesDetail("my", id).getLastUpdateUser())) {
				throw new ServiceException("非本人不能签入");
			}

			DocFiles newFiles = null;
			if (chunkInfo.getChunkCount() == 1) {
				newFiles = saveToServiceNoChunk(chunkInfo.getFileName(), file);
				docFilesService.filesCheckIn(id, newFiles);
			} else {
				String rootPath = request.getServletContext().getRealPath("/") + "uploadTempDir";
				// 分片上传
				File tempFile = FileUploadUtil.getReadySpace(chunkInfo, rootPath);
				// 分片文件
				// 将inputStream流写入临时文件片中
				if (tempFile == null) {
					result.setSuccess(false);
					result.setMessage("上传失败");
					return result;
				}
				file.transferTo(tempFile);
				// 最后一片文件
				if (chunkInfo.getChunkIndex()!=null&&chunkInfo.getChunkCount()!=null&&
						chunkInfo.getChunkIndex().equals(chunkInfo.getChunkCount())	) {
					// 得到文件的所有分片
					File uploadFile = FileUploadUtil.mergerFile(chunkInfo, rootPath);
					// 将文件保存到指定服务器中
					newFiles = saveFileToService(chunkInfo.getFileName(), uploadFile, file.getContentType());
					// 删除合并的文件
					FileUtil.deleteDirectory(FileUploadUtil.getChunkFlod(chunkInfo, rootPath));
					docFilesService.filesCheckIn(id, newFiles);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}
		}

		return result;
	}

	// 文件的历史版本信息列表
	@RequestMapping(value = "/files/version", method = RequestMethod.POST)
	public @ResponseBody ResultBean queryFilesversion(@RequestBody DocFileHisQueryBean bean) {
		ResultBean result = new ResultBean(true, null);
		try {
			result.setObject(docFilesService.queryFilesHisVersion(bean));
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}
		}
		return result;
	}

	// 文件的历史版本信息列表
	@RequestMapping(value = "/files/versionDownLoad", method = RequestMethod.POST)
	public @ResponseBody ResultBean downLoad(@RequestParam Integer id, @RequestParam(required = false) String type,
			HttpServletResponse response) {
		ResultBean result = new ResultBean(true, null);
		try {
			DocFileHis doc = docFilesService.queryFilesHisById(id);
			download(doc.getFilePath() + doc.getSysName(), response, doc.getRealName());
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
		}
		return result;
	}

	/**
	 * 文件上傳
	 * 
	 * @param file
	 * @param request
	 * @param model
	 * @return
	 */
	// @RequestMapping(value = "/files/upload")
	public @ResponseBody ResultBean upload(@RequestParam("files") MultipartFile[] files, HttpServletResponse response,
			HttpServletRequest request, ModelMap model) {
		ResultBean result = new ResultBean(true, "");
		String fileSaveType = "2";
		String configSaveType = ConfigUtil.getValue("upload.saveType");
		if (StringUtils.isNotBlank(configSaveType)) {
			fileSaveType = configSaveType;
		}
		// fileSaveType 为空或者为1 默认传到指定目录
		// fileSaveType 为2 上传到oss服务器
		String path = ConfigUtil.getUploadDir();
		try {
			List<DocFiles> atts = new ArrayList<>();
			for (int i = 0; i < files.length; i++) {
				MultipartFile uploadFile = files[i];
				String sysFileName = uploadFile.getOriginalFilename();
				DocFiles attr = new DocFiles();
				if (StringUtils.isBlank(fileSaveType) || fileSaveType.equals("1")) {
					sysFileName = FileUtil.saveFile(path, sysFileName, uploadFile);
				} else if (fileSaveType.equals("2")) {// oss
					sysFileName = new StringBuffer(sysFileName.substring(0, sysFileName.lastIndexOf("."))).append("-")
							.append(UUID.randomUUID().toString())
							.append(sysFileName.substring(sysFileName.lastIndexOf("."))).toString();
					String accesskeyid = ConfigUtil.getValue("oss.manager.accesskeyid");
					String accesskeysecret = ConfigUtil.getValue("oss.manager.accesskeysecret");
					String bucket = ConfigUtil.getValue("oss.manager.bucket");
					AliyunOSSUtil util = AliyunOSSUtil.getInstance(accesskeyid, accesskeysecret, bucket);
					File f = (File) uploadFile;
					path = "imgs/" + DateUtils.format(new Date()) + "/";
					String ossFieldId = util.uploadObject2OSS(f, sysFileName, path);
					attr.setOssFieldId(ossFieldId);
				}

				attr.setFileSaveType(fileSaveType);
				attr.setFilePath(path);
				attr.setFileExt(uploadFile.getContentType());
				attr.setIsDelete(0);
				attr.setRealName(uploadFile.getOriginalFilename());
				attr.setSysName(sysFileName);
				atts.add(attr);
			}

			// List<FileUploadReturnBean> attrids =
			// docFilesService.saveDocFiles(atts);
			// result.setObject(attrids);

		} catch (Exception e) {
			e.printStackTrace();
			logger.error("上传文件出错", e);
		}
		return result;
	}

	// 文件下载
	@RequestMapping(value = "/files/download", method = RequestMethod.POST)
	public @ResponseBody ResultBean filesDoenload(@RequestParam Integer id, @RequestParam(required = false) String type,
			HttpServletResponse response) {
		ResultBean result = new ResultBean(true, null);
		try {
			// 判断有没有权限
			if(docUserService.queryDocUser().getDefaultUser()!=1){
			if (StringUtil.isNullOrBlank(type)) {
				if (docFolderService.checkFolderPur(docFilesService.queryGroupIdByFileId(id),
						DocConstant.DocPurviews.PURCODE_FILE_DOWNLOAD) == 0) {
					throw new ServiceException("PURCODE_PURCODE_FILE_DOWNLOAD_ERROR");// 没有查询文件列表的权限
				}
			}}
			DocFiles doc = docFilesService.queryFilesDetail(type, id);
			download(doc.getFilePath() + doc.getSysName(), response, doc.getRealName());
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
		}
		return result;
	}

	/**
	 * 附件下载
	 * 
	 * @return
	 * @throws IOException
	 */
	public HttpServletResponse download(String path, HttpServletResponse response, String realName) {
		try {
			// path是指欲下载的文件的路径。
			File file = new File(path);
			// 取得文件名。
			String filename = file.getName();
			// 取得文件的后缀名。
			String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
			// 以流的形式下载文件。
			InputStream fis = new BufferedInputStream(new FileInputStream(path));
			byte[] buffer = new byte[fis.available()];
			fis.read(buffer);
			fis.close();
			// 清空response
			response.reset();
			// 设置response的Header
			response.addHeader("Content-Disposition",
					"attachment;filename=" + new String(realName.getBytes("UTF-8"), "ISO8859-1"));
			response.addHeader("Content-Length", "" + file.length());
			OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/octet-stream");
			toClient.write(buffer);
			toClient.flush();
			toClient.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		return response;
	}

	// 文件保存
	@RequestMapping(value = "/files/fileSave", method = RequestMethod.POST)
	public @ResponseBody ResultBean fileSave(@RequestBody DocFileFormBean docFileFormBean) {
		ResultBean result = new ResultBean(true, null);
		try {
			Integer folderId = Integer.parseInt(docFileFormBean.getId().split("_")[1]);
			docFilesService.saveDocFileForm(folderId, docFileFormBean);
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
		}
		return result;
	}

	// 文件修改摘要
	@RequestMapping(value = "/files/updateFilesKeyword", method = RequestMethod.POST)
	public @ResponseBody ResultBean updateFilesKeyword(@RequestBody DocFilesBean docFilesBean) {
		ResultBean result = new ResultBean(true, null);
		try {
			docFilesService.updateFilesKeywordOrDigest(docFilesBean);
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}
		}
		return result;
	}

	// 文件修改关键字
	@RequestMapping(value = "/files/updateFilesDigest", method = RequestMethod.POST)
	public @ResponseBody ResultBean updateFilesDigest(@RequestBody DocFilesBean docFilesBean) {
		ResultBean result = new ResultBean(true, null);
		try {
			docFilesService.updateFilesKeywordOrDigest(docFilesBean);
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			if (e instanceof ServiceException) {
				result.setErrorCode(e.getMessage());
			} else {
				result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
			}
		}
		return result;
	}

	// 文件删除
	@RequestMapping(value = "/files/delete", method = RequestMethod.POST)
	public @ResponseBody ResultBean filesDelete(@RequestBody DocPortalQuery query) {
		ResultBean result = new ResultBean(true, null);
		try {
			docFilesService.deleteDocFiles(query.getType(), query.getId());
		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
		}
		return result;
	}

	// 文件上传进度
	@RequestMapping(value = "/files/uploadjindu", method = RequestMethod.POST)
	public @ResponseBody ResultBean uploadjindu(@RequestParam String id) {
		ResultBean result = new ResultBean(true, null);
		try {

		} catch (Exception e) {
			e.printStackTrace();
			result.setSuccess(false);
			result.setErrorCode(ResultBean.ERROR_CODE_SYSTEM);
		}
		return result;
	}

	/**
	 * 分片上传文件
	 * 
	 * @param files
	 * @param response
	 * @param request
	 * @param model
	 * @return ResultBean
	 * @Author Administrator
	 * @Date 2017年9月13日
	 */

	@RequestMapping(value = "/files/upload")
	public @ResponseBody ResultBean shardUpload(@RequestParam("files") MultipartFile file, HttpServletResponse response,
			HttpServletRequest request, FileChunkInfo chunkInfo, @RequestParam("abstractStr") String abstractStr,
			@RequestParam("keyword") String keyword, @RequestParam("id") String id) {

		ResultBean result = new ResultBean(true, "");
		String rootPath = request.getServletContext().getRealPath("/") + "uploadTempDir";
		List<DocFiles> atts = new ArrayList<DocFiles>();
		try {
			if (chunkInfo.getChunkCount() > 1) {
				// 分片上传
				File tempFile = FileUploadUtil.getReadySpace(chunkInfo, rootPath);
				// 分片文件
				// 将inputStream流写入临时文件片中
				if (tempFile == null) {
					result.setSuccess(false);
					result.setMessage("上传失败");
					return result;
				}
				file.transferTo(tempFile);
				// 最后一片文件
				if (chunkInfo.getChunkIndex()!=null&&chunkInfo.getChunkCount()!=null&&
						chunkInfo.getChunkIndex().equals(chunkInfo.getChunkCount())	) {
					// 得到文件的所有分片
					File uploadFile = FileUploadUtil.mergerFile(chunkInfo, rootPath);
					// 将文件保存到指定服务器中
					DocFiles att = saveFileToService(chunkInfo.getFileName(), uploadFile, file.getContentType());
					atts.add(att);
					// 删除合并的文件
					FileUtil.deleteDirectory(FileUploadUtil.getChunkFlod(chunkInfo, rootPath));
				}
			} else {
				DocFiles att = saveToServiceNoChunk(chunkInfo.getFileName(), file);
				atts.add(att);
			}
			if (!atts.isEmpty()) {
				String formId = chunkInfo.getUuid();
				Integer folderId = Integer.parseInt(id.split("_")[1]);
				// 保存文件上传记录
				docFilesService.saveDocFiles(abstractStr, keyword, folderId, formId, atts);
				result.setMessage("保存成功！");
			}
		} catch (Exception e) {
			result.setSuccess(false);
			e.printStackTrace();
		}
		return result;

	}

	/**
	 * 不分片直接上传文件
	 * 
	 * @param sysFileName
	 * @param uploadFile
	 * @return DocFiles
	 * @Author Administrator
	 * @Date 2017年9月21日
	 */
	private DocFiles saveToServiceNoChunk(String fileName, MultipartFile uploadFile) {
		String path = ConfigUtil.getUploadDir();
		String fileSaveType = "1";
		String configSaveType = ConfigUtil.getValue("upload.saveType");
		String sysFileName = fileName;
		if (StringUtils.isNotBlank(configSaveType)) {
			fileSaveType = configSaveType;
		}
		DocFiles attr = new DocFiles();
		if (StringUtils.isBlank(fileSaveType) || fileSaveType.equals("1")) {
			sysFileName = FileUtil.saveFile(path, sysFileName, uploadFile);
		} else if (fileSaveType.equals("2")) {// oss
			sysFileName = new StringBuffer(fileName.substring(0, fileName.lastIndexOf("."))).append("-")
					.append(UUID.randomUUID().toString()).append(fileName.substring(fileName.lastIndexOf(".")))
					.toString();
			String accesskeyid = ConfigUtil.getValue("oss.manager.accesskeyid");
			String accesskeysecret = ConfigUtil.getValue("oss.manager.accesskeysecret");
			String bucket = ConfigUtil.getValue("oss.manager.bucket");
			AliyunOSSUtil util = AliyunOSSUtil.getInstance(accesskeyid, accesskeysecret, bucket);
			File f = (File) uploadFile;
			path = "imgs/" + DateUtils.format(new Date()) + "/";
			String ossFieldId = util.uploadObject2OSS(f, sysFileName, path);
			attr.setOssFieldId(ossFieldId);
		}

		attr.setFileSaveType(fileSaveType);
		attr.setFilePath(path);
		attr.setFileExt(uploadFile.getContentType());
		attr.setIsDelete(0);
		attr.setRealName(fileName);
		attr.setSysName(sysFileName);
		attr.setFileSize(FileUploadUtil.fileSizeUnitToString(uploadFile.getSize()));
		return attr;
	}

	/**
	 * 
	 * @param fileName
	 * @param sysFileName
	 * @param atts
	 * @param file
	 * @param uploadFile
	 *            待上传的文件 void
	 * @Author Administrator
	 * @Date 2017年9月21日
	 */
	private DocFiles saveFileToService(String fileName, File uploadFile, String contentType) {
		if(uploadFile==null){
			return null;
		}
		String sysFileName = null;
		String fileSaveType = "1";
		String configSaveType = ConfigUtil.getValue("upload.saveType");
		if (StringUtils.isNotBlank(configSaveType)) {
			fileSaveType = configSaveType;
		}
		// fileSaveType 为空或者为1 默认传到指定目录, fileSaveType 为2 上传到oss服务器
		String path = ConfigUtil.getUploadDir();
		DocFiles attr = new DocFiles();
		if (StringUtils.isBlank(fileSaveType) || fileSaveType.equals("1")) {
			sysFileName = FileUploadUtil.saveFile(path, fileName, uploadFile);
		} else if (fileSaveType.equals("2")) {// oss
			sysFileName = new StringBuffer(fileName.substring(0, fileName.lastIndexOf("."))).append("-")
					.append(UUID.randomUUID().toString()).append(fileName.substring(fileName.lastIndexOf(".")))
					.toString();
			String accesskeyid = ConfigUtil.getValue("oss.manager.accesskeyid");
			String accesskeysecret = ConfigUtil.getValue("oss.manager.accesskeysecret");
			String bucket = ConfigUtil.getValue("oss.manager.bucket");
			AliyunOSSUtil util = AliyunOSSUtil.getInstance(accesskeyid, accesskeysecret, bucket);
			path = "imgs/" + DateUtils.format(new Date()) + "/";
			String ossFieldId = util.uploadObject2OSS(uploadFile, sysFileName, path);
			attr.setOssFieldId(ossFieldId);
		}
		attr.setFileSaveType(fileSaveType);
		attr.setFilePath(path);
		attr.setFileExt(contentType);
		attr.setIsDelete(0);
		attr.setRealName(fileName);
		attr.setSysName(sysFileName);
		attr.setFileSize(FileUploadUtil.fileSizeUnitToString(uploadFile.length()));
		return attr;
	}
}











